#include <iostream>

using std::cout;
using std::endl;

template <class T>
class HasFriend
{
private:
    T item;
    static int ct;

public:
    HasFriend(const T &i) : item(i) { ct++; }
    ~HasFriend() { ct--; }
    friend void count();
    friend void report(HasFriend<T> & hf);
};

template <class T>
int HasFriend<T>::ct = 0;

void count()
{
    cout << "int count: " << HasFriend<int>::ct << " ;" << endl;
    cout << "double count: " << HasFriend<double>::ct << " ;" << endl;
}

template <class T>
void report(HasFriend<T> &hf)
{
    cout << "HasFriend<T> object: " << hf.item << endl;
}

void report(HasFriend<int> &hf)
{
    cout << "HasFriend<int> object: " << hf.item << endl;
}

void report(HasFriend<double> &hf)
{
    cout << "HasFriend<double> object: " << hf.item << endl;
}

int main(int argc, char const *argv[])
{
    cout<<"[mian]-No objects declared:\n";
    count();
    HasFriend<int> hfi1(10);
    cout<<"[mian]-declared a HasFriend<int>:\n";
    count();
    HasFriend<double> hfd1(10.5);
    cout<<"[mian]-declared a HasFriend<double>:\n";
    count();
    HasFriend<int> hfi2(10);
    cout<<"[mian]-declared a HasFriend<int>:\n";
    count();
    return 0;
}
